<!DOCTYPE html>



  


<html class="theme-next muse use-motion" lang="zh-CN">
<head><meta name="generator" content="Hexo 3.9.0">
  <meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<meta name="theme-color" content="#222">









<meta http-equiv="Cache-Control" content="no-transform">
<meta http-equiv="Cache-Control" content="no-siteapp">
















  
  
  <link href="/blog/lib/fancybox/source/jquery.fancybox.css?v=2.1.5" rel="stylesheet" type="text/css">







<link href="/blog/lib/font-awesome/css/font-awesome.min.css?v=4.6.2" rel="stylesheet" type="text/css">

<link href="/blog/css/main.css?v=5.1.4" rel="stylesheet" type="text/css">


  <link rel="apple-touch-icon" sizes="180x180" href="/blog/images/apple-touch-icon-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="32x32" href="/blog/images/favicon-32x32-next.png?v=5.1.4">


  <link rel="icon" type="image/png" sizes="16x16" href="/blog/images/favicon-16x16-next.png?v=5.1.4">


  <link rel="mask-icon" href="/blog/images/logo.svg?v=5.1.4" color="#222">





  <meta name="keywords" content="Hexo, NexT">










<meta name="description" content="JVM的内存管理Java将内存管理的权力交给了JVM自己，因此我们在写代码的时候，可以不花精力在内存分配，垃圾回收这些需求之外的事情上。这样的好处显而易见，降低了编程的复杂度，提高了我们效率，也因为如此，大部分的对JVM垃圾收集器不熟悉的程序员，在经历JVM频繁GC的时候会无从下手。 jvm运行时内存 程序计数器 用来记录程序执行到哪一行，字节码解释器会通过这个值来决定下一条要执行的字节码。一个处">
<meta property="og:type" content="article">
<meta property="og:title" content="垃圾收集器">
<meta property="og:url" content="https://arrycoder.gitee.io/jvm/collector/index.html">
<meta property="og:site_name" content="arry&#39;s blog">
<meta property="og:description" content="JVM的内存管理Java将内存管理的权力交给了JVM自己，因此我们在写代码的时候，可以不花精力在内存分配，垃圾回收这些需求之外的事情上。这样的好处显而易见，降低了编程的复杂度，提高了我们效率，也因为如此，大部分的对JVM垃圾收集器不熟悉的程序员，在经历JVM频繁GC的时候会无从下手。 jvm运行时内存 程序计数器 用来记录程序执行到哪一行，字节码解释器会通过这个值来决定下一条要执行的字节码。一个处">
<meta property="og:locale" content="zh-CN">
<meta property="og:updated_time" content="2020-07-07T01:33:32.883Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="垃圾收集器">
<meta name="twitter:description" content="JVM的内存管理Java将内存管理的权力交给了JVM自己，因此我们在写代码的时候，可以不花精力在内存分配，垃圾回收这些需求之外的事情上。这样的好处显而易见，降低了编程的复杂度，提高了我们效率，也因为如此，大部分的对JVM垃圾收集器不熟悉的程序员，在经历JVM频繁GC的时候会无从下手。 jvm运行时内存 程序计数器 用来记录程序执行到哪一行，字节码解释器会通过这个值来决定下一条要执行的字节码。一个处">



<script type="text/javascript" id="hexo.configurations">
  var NexT = window.NexT || {};
  var CONFIG = {
    root: '/blog/',
    scheme: 'Muse',
    version: '5.1.4',
    sidebar: {"position":"left","display":"post","offset":12,"b2t":false,"scrollpercent":false,"onmobile":false},
    fancybox: true,
    tabs: true,
    motion: {"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}},
    duoshuo: {
      userId: '0',
      author: 'Author'
    },
    algolia: {
      applicationID: '',
      apiKey: '',
      indexName: '',
      hits: {"per_page":10},
      labels: {"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}
    }
  };
</script>



  <link rel="canonical" href="https://arrycoder.gitee.io/jvm/collector/">





  <title>垃圾收集器 | arry's blog</title>
  





  <script type="text/javascript">
    var _hmt = _hmt || [];
    (function() {
      var hm = document.createElement("script");
      hm.src = "https://hm.baidu.com/hm.js?97f9adfda8d04eb91dd054a98264d191";
      var s = document.getElementsByTagName("script")[0];
      s.parentNode.insertBefore(hm, s);
    })();
  </script>




</head>

<body itemscope itemtype="http://schema.org/WebPage" lang="zh-CN">

  
  
    
  

  <div class="container sidebar-position-left page-post-detail">
    <div class="headband"></div>

    <header id="header" class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-wrapper">
  <div class="site-meta ">
    

    <div class="custom-logo-site-title">
      <a href="/blog/" class="brand" rel="start">
        <span class="logo-line-before"><i></i></span>
        <span class="site-title">arry's blog</span>
        <span class="logo-line-after"><i></i></span>
      </a>
    </div>
      
        <p class="site-subtitle"></p>
      
  </div>

  <div class="site-nav-toggle">
    <button>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
      <span class="btn-bar"></span>
    </button>
  </div>
</div>

<nav class="site-nav">
  

  
    <ul id="menu" class="menu">
      
        
        <li class="menu-item menu-item-home">
          <a href="/blog/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-home"></i> <br>
            
            Home
          </a>
        </li>
      
        
        <li class="menu-item menu-item-tags">
          <a href="/blog/tags/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-tags"></i> <br>
            
            Tags
          </a>
        </li>
      
        
        <li class="menu-item menu-item-categories">
          <a href="/blog/categories/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-th"></i> <br>
            
            Categories
          </a>
        </li>
      
        
        <li class="menu-item menu-item-archives">
          <a href="/blog/archives/" rel="section">
            
              <i class="menu-item-icon fa fa-fw fa-archive"></i> <br>
            
            Archives
          </a>
        </li>
      

      
    </ul>
  

  
</nav>



 </div>
    </header>

    <main id="main" class="main">
      <div class="main-inner">
        <div class="content-wrap">
          <div id="content" class="content">
            

  <div id="posts" class="posts-expand">
    

  

  
  
  

  <article class="post post-type-normal" itemscope itemtype="http://schema.org/Article">
  
  
  
  <div class="post-block">
    <link itemprop="mainEntityOfPage" href="https://arrycoder.gitee.io/blog/jvm/collector/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="name" content="arry">
      <meta itemprop="description" content>
      <meta itemprop="image" content="/blog/uploads/avatar.jpg">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="arry's blog">
    </span>

    
      <header class="post-header">

        
        
          <h1 class="post-title" itemprop="name headline">垃圾收集器</h1>
        

        <div class="post-meta">
          <span class="post-time">
            
              <span class="post-meta-item-icon">
                <i class="fa fa-calendar-o"></i>
              </span>
              
                <span class="post-meta-item-text">Posted on</span>
              
              <time title="Post created" itemprop="dateCreated datePublished" datetime="2020-05-18T16:18:59+08:00">
                2020-05-18
              </time>
            

            

            
          </span>

          
            <span class="post-category">
            
              <span class="post-meta-divider">|</span>
            
              <span class="post-meta-item-icon">
                <i class="fa fa-folder-o"></i>
              </span>
              
                <span class="post-meta-item-text">In</span>
              
              
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/blog/categories/JVM/" itemprop="url" rel="index">
                    <span itemprop="name">JVM</span>
                  </a>
                </span>

                
                
              
            </span>
          

          
            
          

          
          

          

          

          

        </div>
      </header>
    

    
    
    
    <div class="post-body" itemprop="articleBody">

      
      

      
        <h2 id="JVM的内存管理"><a href="#JVM的内存管理" class="headerlink" title="JVM的内存管理"></a>JVM的内存管理</h2><p>Java将内存管理的权力交给了JVM自己，因此我们在写代码的时候，可以不花精力在内存分配，垃圾回收这些需求之外的事情上。这样的好处显而易见，降低了编程的复杂度，提高了我们效率，也因为如此，大部分的对JVM垃圾收集器不熟悉的程序员，在经历JVM频繁GC的时候会无从下手。</p>
<h3 id="jvm运行时内存"><a href="#jvm运行时内存" class="headerlink" title="jvm运行时内存"></a>jvm运行时内存</h3><ul>
<li>程序计数器<ul>
<li>用来记录程序执行到哪一行，字节码解释器会通过这个值来决定下一条要执行的字节码。一个处理器只会执行一个线程中的字节码，因此每个线程都会有一块内存用来储存这个计数器的值，当线程切换后能恢复到正确的执行位置。</li>
</ul>
</li>
<li>虚拟机栈<ul>
<li>Java中每个方法的执行，都是一个栈帧入栈出栈的过程。栈帧上存储着局部变量表，局部变量表里则存着基本数据类型和对象引用。</li>
<li>栈帧里还记录着方法的入口，方法的返回，动态链接和操作数栈</li>
</ul>
</li>
<li>本地方法栈<ul>
<li>和虚拟机栈功能差不多，只不过一个执行的是字节码，一个执行的是本地方法。</li>
</ul>
</li>
<li>堆<ul>
<li>用来存储对象实例的区域，也是内存管理最主要的工作区间。</li>
<li>通常所有实例对象都存储在堆上面，但是因为逃逸分析和TLAB，这件事并不是那么绝对<ul>
<li>逃逸分析<br>没有逃逸的对象，可以直接在栈上分配。如果一个对象只给一个线程访问，就可以直接访问，无需加同步保护，可以提升效率（被赋值给全局变量，当作返回值返回，或者当作参数传递给其他方法）​​</li>
<li>TLAB（Thread-local allocation buffer）<br>在eden区中，给每一个线程开辟一块区域，小对象会默认存放在这块区域。因为TLAB是线程私有的，所以免去了锁开销。​​</li>
</ul>
</li>
<li>对象分配的过程<ul>
<li>1.TLAB区如果空间足够，则直接分配</li>
<li>2.TLAB空间不足，就多开一块TLAB空间来分配</li>
<li>3.如果仍然不足，则对eden区加锁，分配对象</li>
<li>4.eden区不足，则进行一次youngGC</li>
<li>5.youngGC后仍然不足，就直接分配到老年代（担保分配）</li>
</ul>
</li>
</ul>
</li>
<li>方法区<ul>
<li>存放已经被加载的类信息，常量池，静态变量和即使编译器编译之后的代码。方法区也被叫做永久代，主要是因为垃圾回收器也会在这块区域工作，主要负责的是类的卸载和常量池的回收。Java8之后将方法区的实现移到了堆外内存里，主要是为了避免方法区产生OOM。但是堆外内存也是受计算机本身的内存限制的，所以在虚拟机启动的时候最好也要指定一下MaxMetaSpaceSize，来防止无限制的扩容引起操作系统的kill操作。</li>
</ul>
</li>
<li>运行时常量池<ul>
<li>属于方法区的一部分。Class文件除了类版本，字段，方法，接口描述信息等，还有一块常量池，用来存放编译期产生的各种字面量和符号引用，在类加载之后，这块内容会存放到运行时常量池里。</li>
<li>运行时常量池是动态的，所以在运行期间，也可以将内容存放到池中。</li>
</ul>
</li>
</ul>
<h2 id="垃圾回收"><a href="#垃圾回收" class="headerlink" title="垃圾回收"></a>垃圾回收</h2><p>垃圾回收，主要针对的是堆和方法区，因为这两块区域是所有线程共享的，在两块区域上存储的东西都是动态的，无法预测的，所以在程序运行过程中，就需要回收掉没用的“垃圾”，并且负责给新的对象分配空间。</p>
<h3 id="哪些对象需要被回收"><a href="#哪些对象需要被回收" class="headerlink" title="哪些对象需要被回收"></a>哪些对象需要被回收</h3><h4 id="引用计数法"><a href="#引用计数法" class="headerlink" title="引用计数法"></a>引用计数法</h4><p>这是一种比较简单的判断方法，当一个对象被引用一次的时候，就加1，如果这个对象被引用的次数为0的时候，说明该对象可以被回收了。这种方法的优点是 判断效率高，算法简单，但是无法解决循环依赖，当出现环状引用的时候，就会导致内存泄漏，无法回收这些对象。</p>
<h4 id="GC-Root"><a href="#GC-Root" class="headerlink" title="GC Root"></a>GC Root</h4><p>根搜索算法是指通过一系列称为GC Root的对象往下搜索，所有走过的路径叫做引用链，当搜索完成之后，所有不可达的对象就会被判定成需要回收的对象。</p>
<p>可作为GC Root的对象有</p>
<ol>
<li>栈帧中引用的对象</li>
<li>静态属性引用的对象</li>
<li>常量引用的对象</li>
<li>Native方法引用的对象</li>
</ol>
<h4 id="引用"><a href="#引用" class="headerlink" title="引用"></a>引用</h4><ul>
<li><p>强引用：类似Object obj = new Object()；只要有强引用，那么该对象就不会被回收</p>
</li>
<li><p>软引用：只有当内存即将溢出的时候，才会将软引用作二次回收</p>
</li>
<li><p>弱引用（Weak Reference）：只能生存到下一次垃圾回收。</p>
</li>
<li><p>虚引用 ：这个引用对于对象生命周期来说没有任何影响</p>
</li>
</ul>
<h4 id="方法区的回收"><a href="#方法区的回收" class="headerlink" title="方法区的回收"></a>方法区的回收</h4><ol>
<li>常量没有被引用的时候就可以回收了</li>
<li>Class<ol>
<li>堆中已经没有该Class的实例</li>
<li>加载该类的ClassLoader已经被回收</li>
<li>对应的Class对象没有被引用，无法在任何地方通过反射调用该类</li>
</ol>
</li>
</ol>
<h3 id="垃圾回收算法"><a href="#垃圾回收算法" class="headerlink" title="垃圾回收算法"></a>垃圾回收算法</h3><h4 id="复制"><a href="#复制" class="headerlink" title="复制"></a>复制</h4><p>将内存分为两个区域，当一个区域无法分配内存的时候，把一个区域的对象全部复制到另外一块内存里。这个算法实现简单，运行高效，但是在内存中总会有一块区域无法使用。这种算法主要是用于新生代里，因为新生代的对象生命周期都很短，所以不需要一半一半的内存分配，而是将内存分成 survivor和eden区域，survivor又分成 from survivor 和 to survivor，一次垃圾回收的流程就是将所有 from和eden区域的所有对象分配到 to survivor区域里，最后清理掉eden和 from survivor区域。survivor和eden区域默认比例是2/8，因此每次新生代可用内存都是 90%。</p>
<p>当另一块survivor区域的大小不够放的时候，就会有内存分配担保机制来保证新对象可以正常分配。在分配之前会先判断老年代是否有足够的连续空间用来存放这些对象，如果够的话，就直接将这些对象放到老年代，如果老年代也不够的话，那么就直接发起一次full gc。</p>
<h4 id="标记-清除"><a href="#标记-清除" class="headerlink" title="标记-清除"></a>标记-清除</h4><p>标记出所有需要回收的对象，然后在回收这些对象。这个算法的全局标记效率太低，同时会产生大量的内存碎片，当分配大对象的时候会导致不得不再触发一次垃圾回收。</p>
<h4 id="标记-整理"><a href="#标记-整理" class="headerlink" title="标记-整理"></a>标记-整理</h4><p>标记所有需要回收的对象，然后将所有存活的对象向一段移动，这样就保证不会有内存碎片</p>
<h4 id="分代收集算法"><a href="#分代收集算法" class="headerlink" title="分代收集算法"></a>分代收集算法</h4><p>因为老年代和新生代数据生命周期的差异，所以将堆分为老年代和新生代，对不同区域使用不同的垃圾回收器。在新生代中，因为每次gc存活的对象都很少，所以可以直接使用复制算法，只需少量的复制成本和空间，就能完成GC。而老年代因为对象存活率高，同时没有额外的空间作分配担保，所以必须使用标记-清除/ 标记-整理算法。</p>
<h3 id="垃圾回收器"><a href="#垃圾回收器" class="headerlink" title="垃圾回收器"></a>垃圾回收器</h3><h5 id="Serial"><a href="#Serial" class="headerlink" title="Serial"></a>Serial</h5><p>串行，单线程收集器，停止用户线程执行垃圾收集。</p>
<h5 id="ParNew"><a href="#ParNew" class="headerlink" title="ParNew"></a>ParNew</h5><p>并行，Serial多线程版本，仍然需要stop the world来执行垃圾收集。可以与CMS搭配使用。</p>
<h5 id="ParallelScavenge"><a href="#ParallelScavenge" class="headerlink" title="ParallelScavenge"></a>ParallelScavenge</h5><p>并行的垃圾收集器，目的是为了达到一个可控的吞吐率。</p>
<p>吞吐率 = 运行用户代码时间 / （运行用户代码时间 + 垃圾手机时间）。高吞吐率的收集器可以高效率的利用CPU，ParallelScavenge通过两个参数控制吞吐率，分别是控制最大垃圾收集停顿时间的-XX:MaxGCPauseMillis参数以及直接设置吞吐量大小的-XX:GCTimeRatio参数。</p>
<h5 id="Serial-old"><a href="#Serial-old" class="headerlink" title="Serial old"></a>Serial old</h5><p>Serial 的老年代版本</p>
<h5 id="Parallel-Old"><a href="#Parallel-Old" class="headerlink" title="Parallel Old"></a>Parallel Old</h5><p>搭配ParallelScavenge使用的并发收集器</p>
<h5 id="CMS（concurrent-mark-sweep）"><a href="#CMS（concurrent-mark-sweep）" class="headerlink" title="CMS（concurrent mark sweep）"></a>CMS（concurrent mark sweep）</h5><p>初始标记（stw）-&gt;并发标记-&gt;重新标记-&gt;并发清除。</p>
<p>初始标记的时候先直接标记gc root，然后并发标记的线程和用户线程一起工作，等并发标记结束之后，再stw重新标记，最后与用户线程并发清除掉这些垃圾。</p>
<ul>
<li><p>Foreground collector</p>
<p>空间不够就执行，不压缩</p>
</li>
<li><p>Background collector</p>
<p>不断扫描，当满足条件的时候就执行，默认是2s。</p>
</li>
</ul>
<p>CMS的缺点</p>
<ol>
<li>使用的是标记-清除算法，会产生大量的内存碎片。</li>
<li>因为与用户线程是并发的，所以对CPU资源是敏感的，当cpu小于4个的时候，会占用一半的资源去做垃圾回收，这对系统运行效率影响是很大的。</li>
<li>因为CMS的标记是和用户线程并发的，所以在cms运行的时候需要预留一部分空间给程序，但是如果预留的空间还不满足程序需求的话，这时候就会临时启用Serial Old来进行一次老年代收集。</li>
</ol>
<h5 id="G1"><a href="#G1" class="headerlink" title="G1"></a>G1</h5><p>Garbage First并不像其他垃圾收集器一样，将堆划分为新生代老年代，而是分为一个个region，region类型有四种 E  S O （eden, survivor, old）Humongous属于old区的一种，humongous（巨大）是其他垃圾收集器没有的概念，这是当分配的对象大于region的一个半的时候，直接分配在Humongous里，当分配的对象大于一个h区的时候，会申请连续的两个h区用来分配。</p>
<h5 id="YoungGC"><a href="#YoungGC" class="headerlink" title="YoungGC"></a>YoungGC</h5><p>对象直接分配到eden区，当eden区不够的时候触发young GC，把e区的数据移到s区，当s区不够的时候直接将eden数据移到o区。S区的对象达到一定年龄也会晋升到o区。</p>
<p>根是young gen，按照young gen个数来控制暂停时间。</p>
<h5 id="MixGC"><a href="#MixGC" class="headerlink" title="MixGC"></a>MixGC</h5><p>根是young gen + 根据统计时间，选出收益高的若干old gen region</p>
<p>在youngGC的时候发现老年代的内存占用达到了threshold，就开始并发标记，当内存分配速度大于MixGC的时候，就会降级成SerialOld收集。</p>
<ul>
<li><p>全局并发标记阶段</p>
<ol>
<li><strong>初始标记</strong> 在youngGC的时候，初始标记gc root直接可达的对象。这里stw是跟着youngGC来的，没有额外的暂停。</li>
<li><strong>并发标记</strong> 不断从扫描栈里取引用递归整个堆，标记所有可达对象，和youngGC同时进行的。在并发标记阶段，如果有引用产生变化，SATB的pre-write-barrier会将这些变化记录下来，collector在收集过程中也会扫描这些引用。</li>
<li><strong>重新标记</strong> stw，标记那些并发标记过程中产生变化而尚未处理的对象（SATB write-barrier），同时在这里处理弱引用。</li>
<li>清理，把没有存活对象的region回收到可分配region列表里。</li>
</ol>
</li>
<li><p>Evacuation阶段（复制）</p>
<p>把一部分region里还存活的对象复制到空region里，然后把原来的region回收。这里会根据用户配置选择合适的region进行回收，而不是把所有region都回收了。</p>
</li>
</ul>
<h2 id="SATB（snapshot-at-beginning）"><a href="#SATB（snapshot-at-beginning）" class="headerlink" title="SATB（snapshot-at-beginning）"></a>SATB（snapshot-at-beginning）</h2><p>当GC开始的时候，已经存活的对象就被认为是活的，这时候的对象图形成一个逻辑快照。同时在pre-write-barrier中，把每次引用关系的改变纪录下来。</p>
<h3 id="三色标记算法"><a href="#三色标记算法" class="headerlink" title="三色标记算法"></a>三色标记算法</h3><p>白色：未扫描或者没被标记到的对象集合</p>
<p>灰色：当前对象已被标记，但是引用尚未标记</p>
<p>黑色：当前对象和引用都已被标记    </p>
<p>因为G1是并发的，垃圾回收线程和mutator是同时执行的，所以要避免两种情况同时发生。</p>
<ol>
<li>把白色对象存到黑色对象的引用里</li>
<li>白色对象丢失了一个灰色对象对其的引用</li>
</ol>
<p>因为黑对象已经被处理过，所以不会再对他进行处理，这时候，白对象丢失了所有灰对象对其的引用，那么就会导致这个白色对象最后扫描不到而被回收。</p>
<p>因此SATB在mark开始的时候，就把所有旧的引用都变成非白的（原本就黑灰的不动，白色的就变成灰色的）。这样就避免了2</p>
<p>在CMS里，当将白色对象分配给黑色对象的时候，就会把该对象变成灰色。避免1</p>
<h3 id="RememberSet"><a href="#RememberSet" class="headerlink" title="RememberSet"></a>RememberSet</h3><p>Remembered Set是在实现部分垃圾收集（partial GC）时用于记录从<strong>非收集部分</strong>指向<strong>收集部分</strong>的指针的<strong>集合</strong>的抽象数据结构。在G1中，每个eden region都有一个RSet，包含了老年代对其的引用。</p>

      
    </div>
    
    
    

    

    

    

    <footer class="post-footer">
      

      
      
      

      
        <div class="post-nav">
          <div class="post-nav-next post-nav-item">
            
              <a href="/blog/git/rebase/" rel="next" title="rebase">
                <i class="fa fa-chevron-left"></i> rebase
              </a>
            
          </div>

          <span class="post-nav-divider"></span>

          <div class="post-nav-prev post-nav-item">
            
              <a href="/blog/jvm/类加载过程/" rel="prev" title="类加载过程">
                类加载过程 <i class="fa fa-chevron-right"></i>
              </a>
            
          </div>
        </div>
      

      
      
    </footer>
  </div>
  
  
  
  </article>



    <div class="post-spread">
      
    </div>
  </div>


          </div>
          


          

  



        </div>
        
          
  
  <div class="sidebar-toggle">
    <div class="sidebar-toggle-line-wrap">
      <span class="sidebar-toggle-line sidebar-toggle-line-first"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-middle"></span>
      <span class="sidebar-toggle-line sidebar-toggle-line-last"></span>
    </div>
  </div>

  <aside id="sidebar" class="sidebar">
    
    <div class="sidebar-inner">

      

      
        <ul class="sidebar-nav motion-element">
          <li class="sidebar-nav-toc sidebar-nav-active" data-target="post-toc-wrap">
            Table of Contents
          </li>
          <li class="sidebar-nav-overview" data-target="site-overview-wrap">
            Overview
          </li>
        </ul>
      

      <section class="site-overview-wrap sidebar-panel">
        <div class="site-overview">
          <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
            
              <img class="site-author-image" itemprop="image" src="/blog/uploads/avatar.jpg" alt="arry">
            
              <p class="site-author-name" itemprop="name">arry</p>
              <p class="site-description motion-element" itemprop="description">Java源码/设计模式/个人记录</p>
          </div>

          <nav class="site-state motion-element">

            
              <div class="site-state-item site-state-posts">
              
                <a href="/blog/archives/">
              
                  <span class="site-state-item-count">42</span>
                  <span class="site-state-item-name">posts</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-categories">
                <a href="/blog/categories/index.html">
                  <span class="site-state-item-count">11</span>
                  <span class="site-state-item-name">categories</span>
                </a>
              </div>
            

            
              
              
              <div class="site-state-item site-state-tags">
                <a href="/blog/tags/index.html">
                  <span class="site-state-item-count">18</span>
                  <span class="site-state-item-name">tags</span>
                </a>
              </div>
            

          </nav>

          

          

          
          

          
          

          

        </div>
      </section>

      
      <!--noindex-->
        <section class="post-toc-wrap motion-element sidebar-panel sidebar-panel-active">
          <div class="post-toc">

            
              
            

            
              <div class="post-toc-content"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#JVM的内存管理"><span class="nav-number">1.</span> <span class="nav-text">JVM的内存管理</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#jvm运行时内存"><span class="nav-number">1.1.</span> <span class="nav-text">jvm运行时内存</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#垃圾回收"><span class="nav-number">2.</span> <span class="nav-text">垃圾回收</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#哪些对象需要被回收"><span class="nav-number">2.1.</span> <span class="nav-text">哪些对象需要被回收</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#引用计数法"><span class="nav-number">2.1.1.</span> <span class="nav-text">引用计数法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#GC-Root"><span class="nav-number">2.1.2.</span> <span class="nav-text">GC Root</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#引用"><span class="nav-number">2.1.3.</span> <span class="nav-text">引用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#方法区的回收"><span class="nav-number">2.1.4.</span> <span class="nav-text">方法区的回收</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#垃圾回收算法"><span class="nav-number">2.2.</span> <span class="nav-text">垃圾回收算法</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#复制"><span class="nav-number">2.2.1.</span> <span class="nav-text">复制</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#标记-清除"><span class="nav-number">2.2.2.</span> <span class="nav-text">标记-清除</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#标记-整理"><span class="nav-number">2.2.3.</span> <span class="nav-text">标记-整理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#分代收集算法"><span class="nav-number">2.2.4.</span> <span class="nav-text">分代收集算法</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#垃圾回收器"><span class="nav-number">2.3.</span> <span class="nav-text">垃圾回收器</span></a><ol class="nav-child"><li class="nav-item nav-level-5"><a class="nav-link" href="#Serial"><span class="nav-number">2.3.0.1.</span> <span class="nav-text">Serial</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ParNew"><span class="nav-number">2.3.0.2.</span> <span class="nav-text">ParNew</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#ParallelScavenge"><span class="nav-number">2.3.0.3.</span> <span class="nav-text">ParallelScavenge</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Serial-old"><span class="nav-number">2.3.0.4.</span> <span class="nav-text">Serial old</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#Parallel-Old"><span class="nav-number">2.3.0.5.</span> <span class="nav-text">Parallel Old</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#CMS（concurrent-mark-sweep）"><span class="nav-number">2.3.0.6.</span> <span class="nav-text">CMS（concurrent mark sweep）</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#G1"><span class="nav-number">2.3.0.7.</span> <span class="nav-text">G1</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#YoungGC"><span class="nav-number">2.3.0.8.</span> <span class="nav-text">YoungGC</span></a></li><li class="nav-item nav-level-5"><a class="nav-link" href="#MixGC"><span class="nav-number">2.3.0.9.</span> <span class="nav-text">MixGC</span></a></li></ol></li></ol></li></ol><li class="nav-item nav-level-2"><a class="nav-link" href="#SATB（snapshot-at-beginning）"><span class="nav-number">3.</span> <span class="nav-text">SATB（snapshot-at-beginning）</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#三色标记算法"><span class="nav-number">3.1.</span> <span class="nav-text">三色标记算法</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#RememberSet"><span class="nav-number">3.2.</span> <span class="nav-text">RememberSet</span></a></li></ol></li></div>
            

          </div>
        </section>
      <!--/noindex-->
      

      

    </div>
  </aside>


        
      </div>
    </main>

    <footer id="footer" class="footer">
      <div class="footer-inner">
        <div class="copyright">&copy; <span itemprop="copyrightYear">2020</span>
  <span class="with-love">
    <i class="fa fa-user"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">arry</span>

  
</div>


  <div class="powered-by">Powered by <a class="theme-link" target="_blank" href="https://hexo.io">Hexo</a></div>



  <span class="post-meta-divider">|</span>



  <div class="theme-info">Theme &mdash; <a class="theme-link" target="_blank" href="https://github.com/iissnan/hexo-theme-next">NexT.Muse</a> v5.1.4</div>




        







        
      </div>
    </footer>

    
      <div class="back-to-top">
        <i class="fa fa-arrow-up"></i>
        
      </div>
    

    

  </div>

  

<script type="text/javascript">
  if (Object.prototype.toString.call(window.Promise) !== '[object Function]') {
    window.Promise = null;
  }
</script>









  












  
  
    <script type="text/javascript" src="/blog/lib/jquery/index.js?v=2.1.3"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fastclick/lib/fastclick.min.js?v=1.0.6"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/jquery_lazyload/jquery.lazyload.js?v=1.9.7"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/velocity/velocity.ui.min.js?v=1.2.1"></script>
  

  
  
    <script type="text/javascript" src="/blog/lib/fancybox/source/jquery.fancybox.pack.js?v=2.1.5"></script>
  


  


  <script type="text/javascript" src="/blog/js/src/utils.js?v=5.1.4"></script>

  <script type="text/javascript" src="/blog/js/src/motion.js?v=5.1.4"></script>



  
  

  
  <script type="text/javascript" src="/blog/js/src/scrollspy.js?v=5.1.4"></script>
<script type="text/javascript" src="/blog/js/src/post-details.js?v=5.1.4"></script>



  


  <script type="text/javascript" src="/blog/js/src/bootstrap.js?v=5.1.4"></script>



  


  




	





  





  












  





  

  

  

  
  

  

  

  

</body>
</html>
